/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * HolidayAdjustmentDialog.java
 *
 * Created on 20-Jul-2010, 06:15:36
 */

package TimeRecording.forms;

import TimeRecording.TimeRecordingView;
import TimeRecording.business.FilteredQuery;
import TimeRecording.business.HolidayCalculations;
import TimeRecording.enums.HolidayAdjustmentStatus;
import TimeRecording.enums.HolidayAdjustmentStatusConverter;
import TimeRecording.enums.HolidayGrantType;
import TimeRecording.tables.Employee;
import TimeRecording.tables.HolidayAdjustment;
import TimeRecording.widgets.DaisyChainCalendar;
import TimeRecording.widgets.EmployeeComboBox;
import TimeRecording.widgets.HolidayGrantTypeComboBox;
import java.beans.Beans;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.swing.JOptionPane;
import org.jdesktop.application.Action;
import org.jdesktop.observablecollections.ObservableCollections;

/**
 *
 * @author david
 */
public class HolidayAdjustmentDialog extends javax.swing.JDialog {

    private final static Logger LOGGER = Logger.getLogger(
            HolidayAdjustmentDialog.class.getName());

    // Dropdown constants

    private final static int ALL_ADJUSTMENTS_ID = 0;
    private final static int THIS_YEARS_ADJUSTMENTS_ID = 1;
    private final static int PAST_ADJUSTMENTS_ID = 2;
    private final static int FUTURE_ADJUSTMENTS_ID = 3;
    private final static int CUSTOM_ADJUSTMENTS_ID = 4;

    private TimeRecordingView myParent;
    private EntityManager entityManager;

    private HolidayAdjustmentStatusConverter statusConverter =
            new HolidayAdjustmentStatusConverter();

    // <editor-fold defaultstate="collapsed" desc="editable">
    protected boolean editable = false;

    public boolean isEditable() {
	return  editable;
    }

    public void setEditable(boolean editable) {
        boolean oldEditable = this.editable;
        this.editable =  editable;
        firePropertyChange("editable", oldEditable, editable);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="editableByAdministrator">
    protected boolean editableByAdministrator = false;

    public boolean isEditableByAdministrator() {
	return  editableByAdministrator;
    }

    public void setEditableByAdministrator(boolean editableByAdministrator) {
        boolean oldEditableByAdministrator = this.editableByAdministrator;
        this.editableByAdministrator =  editableByAdministrator;
        firePropertyChange("editableByAdministrator",
                oldEditableByAdministrator, editableByAdministrator);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="recordSelected">
    protected boolean recordSelected = false;

    public boolean isRecordSelected() {
	return recordSelected;
    }

    public void setRecordSelected(boolean recordSelected) {

        boolean oldRecordSelected = this.recordSelected;
        this.recordSelected = recordSelected;
        firePropertyChange("recordSelected", oldRecordSelected, recordSelected);

        assessWhatShouldBeEnabled();
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="releaseable">
    protected boolean releaseable = false;

    public boolean isReleaseable() {
	return  releaseable;
    }

    public void setReleaseable(boolean releaseable) {
        boolean oldReleaseable = this.releaseable;
        this.releaseable =  releaseable;
        firePropertyChange("releaseable", oldReleaseable, releaseable);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="revokable">
    protected boolean revokable = false;

    public boolean isRevokable() {
	return  revokable;
    }

    public void setRevokable(boolean revokable) {
        boolean oldRevokable = this.revokable;
        this.revokable =  revokable;
        firePropertyChange("revokable", oldRevokable, revokable);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="administratorLoggedIn">
    protected boolean administratorLoggedIn = false;

    public boolean isAdministratorLoggedIn() {
        return administratorLoggedIn;
    }

    public void setAdministratorLoggedIn(boolean administratorLoggedIn) {

        boolean oldAdministratorLoggedIn = this.administratorLoggedIn;
        this.administratorLoggedIn = administratorLoggedIn;
        firePropertyChange("administratorLoggedIn", oldAdministratorLoggedIn, administratorLoggedIn);

        assessWhatShouldBeEnabled();
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="employeeFilterable">
    protected boolean employeeFilterable = false;

    public boolean isEmployeeFilterable() {
        return employeeFilterable;
    }

    public void setEmployeeFilterable(boolean employeeFilterable) {
        boolean oldEmployeeFilterable = this.employeeFilterable;
        this.employeeFilterable = employeeFilterable;
        firePropertyChange("employeeFilterable", oldEmployeeFilterable, employeeFilterable);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="adjustmentTypeFilterable">
    protected boolean adjustmentTypeFilterable = false;

    public boolean isAdjustmentTypeFilterable() {
        return adjustmentTypeFilterable;
    }

    public void setAdjustmentTypeFilterable(boolean adjustmentTypeFilterable) {
        boolean oldAdjustmentTypeFilterable = this.adjustmentTypeFilterable;
        this.adjustmentTypeFilterable = adjustmentTypeFilterable;
        firePropertyChange("adjustmentTypeFilterable",
                oldAdjustmentTypeFilterable, adjustmentTypeFilterable);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="selectedAdjustment">
    private HolidayAdjustment selectedAdjustment;

    public HolidayAdjustment getSelectedAdjustment() {
        return selectedAdjustment;
    }

    public void setSelectedAdjustment(HolidayAdjustment selectedAdjustment) {
        HolidayAdjustment oldSelectedAdjustment = this.selectedAdjustment;
        this.selectedAdjustment = selectedAdjustment;
        firePropertyChange("selectedAdjustment", oldSelectedAdjustment, selectedAdjustment);
        setRecordSelected(selectedAdjustment != null);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="filteredEmployee">
    protected Employee filteredEmployee;

    public Employee getFilteredEmployee() {
        return filteredEmployee;
    }

    public void setFilteredEmployee(Employee filteredEmployee) {
        Employee oldFilteredEmployee = this.filteredEmployee;
        this.filteredEmployee = filteredEmployee;
        firePropertyChange("filteredEmployee", oldFilteredEmployee, filteredEmployee);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="filteredAdjustmentType">
    protected HolidayGrantType filteredAdjustmentType;

    public HolidayGrantType getFilteredAdjustmentType() {
        return filteredAdjustmentType;
    }

    public void setFilteredAdjustmentType(HolidayGrantType filteredAdjustmentType) {
        HolidayGrantType oldFilteredAdjustmentType = this.filteredAdjustmentType;
        this.filteredAdjustmentType = filteredAdjustmentType;
        firePropertyChange("filteredAdjustmentType", oldFilteredAdjustmentType, filteredAdjustmentType);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="filteredStartDate">
    protected Date filteredStartDate;

    public Date getFilteredStartDate() {
        return filteredStartDate;
    }

    public void setFilteredStartDate(Date filteredStartDate) {
        Date oldFilteredStartDate = this.filteredStartDate;
        this.filteredStartDate = filteredStartDate;
        firePropertyChange("filteredStartDate", oldFilteredStartDate, filteredStartDate);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="filteredEndDate">
    protected Date filteredEndDate;

    public Date getFilteredEndDate() {
        return filteredEndDate;
    }

    public void setFilteredEndDate(Date filteredEndDate) {
        Date oldFilteredEndDate = this.filteredEndDate;
        this.filteredEndDate = filteredEndDate;
        firePropertyChange("filteredEndDate", oldFilteredEndDate, filteredEndDate);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="dateComboBeingActioned">

    protected boolean dateComboBeingActioned = false;

    public boolean getDateComboBeingActioned() {
        return dateComboBeingActioned;
    }

    public void setDateComboBeingActioned(boolean dateComboBeingActioned) {
        boolean oldDateComboBeingActioned = this.dateComboBeingActioned;
        this.dateComboBeingActioned = dateComboBeingActioned;
        firePropertyChange("dateComboBeingActioned",
                oldDateComboBeingActioned, dateComboBeingActioned);
    } // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="entityManager Getter & Setter">
    public EntityManager getEntityManager() {
        return entityManager;
    }
    
    public void setEntityManager(EntityManager entityManager) {
        EntityManager oldEntityManager = this.entityManager;
        this.entityManager = entityManager;
        firePropertyChange("entityManager", oldEntityManager, entityManager);
    } // </editor-fold>

    private void assessWhatShouldBeEnabled() {

        setReleaseable(isRecordSelected() &&
                isAdministratorLoggedIn() &&
                status.getText().equals(HolidayAdjustmentStatus.PREPARATION.toString()));

        setRevokable(isRecordSelected() &&
                isAdministratorLoggedIn() &&
                status.getText().equals(HolidayAdjustmentStatus.RELEASED.toString()));

        setEditable(isRecordSelected() &&
                isAdministratorLoggedIn() &&
                !status.getText().equals(HolidayAdjustmentStatus.PROCESSED.toString()) &&
                !status.getText().equals(HolidayAdjustmentStatus.ARCHIVED.toString()));
    }

    /** Creates new form HolidayAdjustmentDialog */
    public HolidayAdjustmentDialog(TimeRecordingView parent,
            EntityManager entityManager, boolean modal) {
        
        super(parent.getFrame(), modal);

        myParent = parent;
        this.entityManager = entityManager;

        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        holidayAdjustmentList = ObservableCollections.observableList(new java.util.LinkedList());
        holidayGrantTypeConverter = new TimeRecording.enums.HolidayGrantTypeConverter();
        dateConverter = new TimeRecording.widgets.DateConverter();
        filterPanel = new javax.swing.JPanel();
        employeeCheck = new javax.swing.JCheckBox();
        employeeFilterCombo = new EmployeeComboBox(entityManager);
        dateFilterLabel = new javax.swing.JLabel();
        dateFilterCombo = new javax.swing.JComboBox();
        dateFilterFromLabel = new javax.swing.JLabel();
        dateFilterFrom = new com.toedter.calendar.JDateChooser();
        dateFilterToLabel = new javax.swing.JLabel();
        dateFilterTo = new com.toedter.calendar.JDateChooser();
        filterButton = new javax.swing.JButton();
        adjustmentTypeFilterCombo = new HolidayGrantTypeComboBox();
        adjustmentTypeCheck = new javax.swing.JCheckBox();
        tablePane = new javax.swing.JScrollPane();
        adjustmentTable = new javax.swing.JTable();
        absenceSummaryPanel = new TimeRecording.forms.AbsenceSummaryPanel();
        detailsPanel = new javax.swing.JPanel();
        employeeLabel = new javax.swing.JLabel();
        employee = new javax.swing.JTextField();
        administratorLabel = new javax.swing.JLabel();
        administrator = new javax.swing.JTextField();
        administratorCommentLabel = new javax.swing.JLabel();
        administratorComment = new javax.swing.JTextField();
        fromLabel = new javax.swing.JLabel();
        fromDate = new javax.swing.JTextField();
        hoursSpentLabel = new javax.swing.JLabel();
        hoursAdjusted = new javax.swing.JFormattedTextField();
        typeLabel = new javax.swing.JLabel();
        type = new javax.swing.JTextField();
        statusLabel = new javax.swing.JLabel();
        status = new javax.swing.JTextField();
        buttonPanel = new javax.swing.JPanel();
        newButton = new javax.swing.JButton();
        editButton = new javax.swing.JButton();
        deleteButton = new javax.swing.JButton();
        releaseButton = new javax.swing.JButton();
        revokeButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(TimeRecording.TimeRecordingApp.class).getContext().getResourceMap(HolidayAdjustmentDialog.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
            public void windowOpened(java.awt.event.WindowEvent evt) {
                formWindowOpened(evt);
            }
        });
        getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.PAGE_AXIS));

        filterPanel.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createEmptyBorder(8, 8, 4, 8), javax.swing.BorderFactory.createTitledBorder("Filter")));
        filterPanel.setName("filterPanel"); // NOI18N
        filterPanel.setLayout(new java.awt.GridBagLayout());

        employeeCheck.setText(resourceMap.getString("employeeCheck.text")); // NOI18N
        employeeCheck.setName("employeeCheck"); // NOI18N

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${employeeFilterable}"), employeeCheck, org.jdesktop.beansbinding.BeanProperty.create("selected"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 4);
        filterPanel.add(employeeCheck, gridBagConstraints);

        employeeFilterCombo.setName("employeeFilterCombo"); // NOI18N
        employeeFilterCombo.setPreferredSize(new java.awt.Dimension(190, 20));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${filteredEmployee}"), employeeFilterCombo, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"));
        bindingGroup.addBinding(binding);
        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${employeeFilterable}"), employeeFilterCombo, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 33.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 4);
        filterPanel.add(employeeFilterCombo, gridBagConstraints);

        dateFilterLabel.setText(resourceMap.getString("dateFilterLabel.text")); // NOI18N
        dateFilterLabel.setName("dateFilterLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 4);
        filterPanel.add(dateFilterLabel, gridBagConstraints);

        dateFilterCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "All", "This Year", "Previous", "Future", "Custom" }));
        dateFilterCombo.setName("dateFilterCombo"); // NOI18N
        dateFilterCombo.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                dateFilterComboItemStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 33.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 4);
        filterPanel.add(dateFilterCombo, gridBagConstraints);

        dateFilterFromLabel.setText(resourceMap.getString("dateFilterFromLabel.text")); // NOI18N
        dateFilterFromLabel.setName("dateFilterFromLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 4);
        filterPanel.add(dateFilterFromLabel, gridBagConstraints);

        dateFilterFrom.setMinimumSize(new java.awt.Dimension(150, 20));
        dateFilterFrom.setName("dateFilterFrom"); // NOI18N
        dateFilterFrom.setPreferredSize(new java.awt.Dimension(120, 20));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${filteredStartDate}"), dateFilterFrom, org.jdesktop.beansbinding.BeanProperty.create("date"));
        bindingGroup.addBinding(binding);

        dateFilterFrom.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                dateFilterFromPropertyChange(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 33.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 4, 4);
        filterPanel.add(dateFilterFrom, gridBagConstraints);

        dateFilterToLabel.setText(resourceMap.getString("dateFilterToLabel.text")); // NOI18N
        dateFilterToLabel.setName("dateFilterToLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 8, 8, 4);
        filterPanel.add(dateFilterToLabel, gridBagConstraints);

        dateFilterTo.setMinimumSize(new java.awt.Dimension(150, 20));
        dateFilterTo.setName("dateFilterTo"); // NOI18N
        dateFilterTo.setPreferredSize(new java.awt.Dimension(120, 20));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${filteredEndDate}"), dateFilterTo, org.jdesktop.beansbinding.BeanProperty.create("date"));
        bindingGroup.addBinding(binding);

        dateFilterTo.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                dateFilterToPropertyChange(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 33.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 0, 8, 4);
        filterPanel.add(dateFilterTo, gridBagConstraints);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(TimeRecording.TimeRecordingApp.class).getContext().getActionMap(HolidayAdjustmentDialog.class, this);
        filterButton.setAction(actionMap.get("applyFilter")); // NOI18N
        filterButton.setText(resourceMap.getString("filterButton.text")); // NOI18N
        filterButton.setName("filterButton"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 8, 8, 8);
        filterPanel.add(filterButton, gridBagConstraints);

        adjustmentTypeFilterCombo.setName("adjustmentTypeFilterCombo"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${filteredAdjustmentType}"), adjustmentTypeFilterCombo, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"));
        bindingGroup.addBinding(binding);
        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${adjustmentTypeFilterable}"), adjustmentTypeFilterCombo, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 33.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 8, 4);
        filterPanel.add(adjustmentTypeFilterCombo, gridBagConstraints);

        adjustmentTypeCheck.setText(resourceMap.getString("adjustmentTypeCheck.text")); // NOI18N
        adjustmentTypeCheck.setName("adjustmentTypeCheck"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${adjustmentTypeFilterable}"), adjustmentTypeCheck, org.jdesktop.beansbinding.BeanProperty.create("selected"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(4, 8, 8, 4);
        filterPanel.add(adjustmentTypeCheck, gridBagConstraints);

        getContentPane().add(filterPanel);

        tablePane.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createEmptyBorder(4, 8, 4, 8), javax.swing.BorderFactory.createEtchedBorder()));
        tablePane.setName("tablePane"); // NOI18N

        adjustmentTable.setAutoCreateRowSorter(true);
        adjustmentTable.setName("adjustmentTable"); // NOI18N

        org.jdesktop.swingbinding.JTableBinding jTableBinding = org.jdesktop.swingbinding.SwingBindings.createJTableBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, holidayAdjustmentList, adjustmentTable);
        org.jdesktop.swingbinding.JTableBinding.ColumnBinding columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${employeeId}"));
        columnBinding.setColumnName("Employee Id");
        columnBinding.setColumnClass(TimeRecording.tables.Employee.class);
        columnBinding.setEditable(false);
        columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${adjustmentDate}"));
        columnBinding.setColumnName("Adjustment Date");
        columnBinding.setColumnClass(java.util.Date.class);
        columnBinding.setEditable(false);
        columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${hoursAdjusted}"));
        columnBinding.setColumnName("Hours Adjusted");
        columnBinding.setColumnClass(Double.class);
        columnBinding.setEditable(false);
        columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${adjustmentType}"));
        columnBinding.setColumnName("Adjustment Type");
        columnBinding.setColumnClass(TimeRecording.enums.HolidayGrantType.class);
        columnBinding.setEditable(false);
        columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${status}"));
        columnBinding.setColumnName("Status");
        columnBinding.setColumnClass(TimeRecording.enums.HolidayAdjustmentStatus.class);
        columnBinding.setEditable(false);
        bindingGroup.addBinding(jTableBinding);
        jTableBinding.bind();binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment}"), adjustmentTable, org.jdesktop.beansbinding.BeanProperty.create("selectedElement"));
        bindingGroup.addBinding(binding);

        tablePane.setViewportView(adjustmentTable);
        adjustmentTable.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("adjustmentTable.columnModel.title0")); // NOI18N
        adjustmentTable.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("adjustmentTable.columnModel.title1")); // NOI18N
        adjustmentTable.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("adjustmentTable.columnModel.title2")); // NOI18N
        adjustmentTable.getColumnModel().getColumn(3).setHeaderValue(resourceMap.getString("adjustmentTable.columnModel.title3")); // NOI18N
        adjustmentTable.getColumnModel().getColumn(4).setHeaderValue(resourceMap.getString("adjustmentTable.columnModel.title4")); // NOI18N

        getContentPane().add(tablePane);

        absenceSummaryPanel.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createEmptyBorder(4, 8, 4, 8), javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("absenceSummaryPanel.border.insideBorder.title")))); // NOI18N
        absenceSummaryPanel.setName("absenceSummaryPanel"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, adjustmentTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement.employeeId.workingPatternsMaster}"), absenceSummaryPanel, org.jdesktop.beansbinding.BeanProperty.create("workingPatternMaster"));
        bindingGroup.addBinding(binding);

        getContentPane().add(absenceSummaryPanel);

        detailsPanel.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createEmptyBorder(1, 8, 1, 8), javax.swing.BorderFactory.createTitledBorder("Grant Details")));
        detailsPanel.setMinimumSize(new java.awt.Dimension(244, 120));
        detailsPanel.setName("detailsPanel"); // NOI18N
        detailsPanel.setLayout(new java.awt.GridBagLayout());

        employeeLabel.setText(resourceMap.getString("employeeLabel.text")); // NOI18N
        employeeLabel.setName("employeeLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 4);
        detailsPanel.add(employeeLabel, gridBagConstraints);

        employee.setEditable(false);
        employee.setName("employee"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment.employeeId.friendlyName}"), employee, org.jdesktop.beansbinding.BeanProperty.create("text"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 25.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 4);
        detailsPanel.add(employee, gridBagConstraints);

        administratorLabel.setText(resourceMap.getString("administratorLabel.text")); // NOI18N
        administratorLabel.setName("administratorLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(administratorLabel, gridBagConstraints);

        administrator.setEditable(false);
        administrator.setName("administrator"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment.administratorId.friendlyName}"), administrator, org.jdesktop.beansbinding.BeanProperty.create("text"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(administrator, gridBagConstraints);

        administratorCommentLabel.setText(resourceMap.getString("administratorCommentLabel.text")); // NOI18N
        administratorCommentLabel.setName("administratorCommentLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(administratorCommentLabel, gridBagConstraints);

        administratorComment.setEditable(false);
        administratorComment.setName("administratorComment"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment.comment}"), administratorComment, org.jdesktop.beansbinding.BeanProperty.create("text"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 75.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(administratorComment, gridBagConstraints);

        fromLabel.setText(resourceMap.getString("fromLabel.text")); // NOI18N
        fromLabel.setName("fromLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(fromLabel, gridBagConstraints);

        fromDate.setEditable(false);
        fromDate.setName("fromDate"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment.adjustmentDate}"), fromDate, org.jdesktop.beansbinding.BeanProperty.create("text"));
        binding.setConverter(dateConverter);
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 50.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(fromDate, gridBagConstraints);

        hoursSpentLabel.setText(resourceMap.getString("hoursSpentLabel.text")); // NOI18N
        hoursSpentLabel.setName("hoursSpentLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 12, 4, 4);
        detailsPanel.add(hoursSpentLabel, gridBagConstraints);

        hoursAdjusted.setEditable(false);
        hoursAdjusted.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0.00"))));
        hoursAdjusted.setName("hoursAdjusted"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment.hoursAdjusted}"), hoursAdjusted, org.jdesktop.beansbinding.BeanProperty.create("value"));
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 50.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(hoursAdjusted, gridBagConstraints);

        typeLabel.setText(resourceMap.getString("typeLabel.text")); // NOI18N
        typeLabel.setName("typeLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 12, 4, 4);
        detailsPanel.add(typeLabel, gridBagConstraints);

        type.setEditable(false);
        type.setName("type"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment.adjustmentType}"), type, org.jdesktop.beansbinding.BeanProperty.create("text"));
        binding.setConverter(holidayGrantTypeConverter);
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 50.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(type, gridBagConstraints);

        statusLabel.setText(resourceMap.getString("statusLabel.text")); // NOI18N
        statusLabel.setName("statusLabel"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 12, 4, 4);
        detailsPanel.add(statusLabel, gridBagConstraints);

        status.setEditable(false);
        status.setName("status"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${selectedAdjustment.status}"), status, org.jdesktop.beansbinding.BeanProperty.create("text"));
        binding.setConverter(statusConverter);
        bindingGroup.addBinding(binding);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 50.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        detailsPanel.add(status, gridBagConstraints);

        getContentPane().add(detailsPanel);

        buttonPanel.setName("buttonPanel"); // NOI18N

        newButton.setAction(actionMap.get("newHolidayAdjustment")); // NOI18N
        newButton.setText(resourceMap.getString("newButton.text")); // NOI18N
        newButton.setName("newButton"); // NOI18N
        buttonPanel.add(newButton);

        editButton.setAction(actionMap.get("editHolidayAdjustment")); // NOI18N
        editButton.setText(resourceMap.getString("editButton.text")); // NOI18N
        editButton.setName("editButton"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${recordSelected}"), editButton, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        buttonPanel.add(editButton);

        deleteButton.setAction(actionMap.get("deleteHolidayAdjustment")); // NOI18N
        deleteButton.setText(resourceMap.getString("deleteButton.text")); // NOI18N
        deleteButton.setName("deleteButton"); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${recordSelected}"), deleteButton, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
        bindingGroup.addBinding(binding);

        buttonPanel.add(deleteButton);

        releaseButton.setAction(actionMap.get("releaseAdjustment")); // NOI18N
        releaseButton.setText(resourceMap.getString("releaseButton.text")); // NOI18N
        releaseButton.setName("releaseButton"); // NOI18N
        buttonPanel.add(releaseButton);

        revokeButton.setAction(actionMap.get("revokeAdjustment")); // NOI18N
        revokeButton.setText(resourceMap.getString("revokeButton.text")); // NOI18N
        revokeButton.setName("revokeButton"); // NOI18N
        buttonPanel.add(revokeButton);

        getContentPane().add(buttonPanel);

        bindingGroup.bind();

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-754)/2, (screenSize.height-488)/2, 754, 488);
    }// </editor-fold>//GEN-END:initComponents

    private void dateFilterFromPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_dateFilterFromPropertyChange
        if (!getDateComboBeingActioned()) {
            dateFilterCombo.setSelectedIndex(CUSTOM_ADJUSTMENTS_ID);
        }
}//GEN-LAST:event_dateFilterFromPropertyChange

    private void dateFilterToPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_dateFilterToPropertyChange
        if (!getDateComboBeingActioned()) {
            dateFilterCombo.setSelectedIndex(CUSTOM_ADJUSTMENTS_ID);
        }
}//GEN-LAST:event_dateFilterToPropertyChange

    private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened

        // Enable/disable buttons based on logged in user

        setAdministratorLoggedIn(myParent.isSupervisorLoggedIn());
        newButton.setVisible(isAdministratorLoggedIn());
        editButton.setVisible(isAdministratorLoggedIn());
        deleteButton.setVisible(isAdministratorLoggedIn());

        // Apply a default filter (this years holidays)

        setEmployeeFilterable(true);
        setFilteredEmployee(myParent.getLoggedInEmployee());

        setAdjustmentTypeFilterable(false);

        dateFilterCombo.setSelectedIndex(THIS_YEARS_ADJUSTMENTS_ID);

        if (!Beans.isDesignTime()) {
            applyFilter();
        }
    }//GEN-LAST:event_formWindowOpened

    private void dateFilterComboItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_dateFilterComboItemStateChanged

        setDateComboBeingActioned(true);

        int selection = dateFilterCombo.getSelectedIndex();

        if (selection == ALL_ADJUSTMENTS_ID) {
            dateFilterFrom.setDate(DaisyChainCalendar.START_OF_TIME);
            dateFilterTo.setDate(DaisyChainCalendar.END_OF_TIME);

        } else if (selection == THIS_YEARS_ADJUSTMENTS_ID) {
            dateFilterFrom.setDate(DaisyChainCalendar.startOfYear());
            dateFilterTo.setDate(DaisyChainCalendar.endOfYear());

        } else if (selection == PAST_ADJUSTMENTS_ID) {
            dateFilterFrom.setDate(DaisyChainCalendar.START_OF_TIME);
            dateFilterTo.setDate(DaisyChainCalendar.endOfToday());

        } else if (selection == FUTURE_ADJUSTMENTS_ID) {
            dateFilterFrom.setDate(DaisyChainCalendar.startOfToday());
            dateFilterTo.setDate(DaisyChainCalendar.END_OF_TIME);
        }

        setDateComboBeingActioned(false);
    }//GEN-LAST:event_dateFilterComboItemStateChanged

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        myParent.hideHolidayAdjustmentDialog();
    }//GEN-LAST:event_formWindowClosing

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private TimeRecording.forms.AbsenceSummaryPanel absenceSummaryPanel;
    private javax.swing.JTable adjustmentTable;
    private javax.swing.JCheckBox adjustmentTypeCheck;
    private javax.swing.JComboBox adjustmentTypeFilterCombo;
    private javax.swing.JTextField administrator;
    private javax.swing.JTextField administratorComment;
    private javax.swing.JLabel administratorCommentLabel;
    private javax.swing.JLabel administratorLabel;
    private javax.swing.JPanel buttonPanel;
    private TimeRecording.widgets.DateConverter dateConverter;
    private javax.swing.JComboBox dateFilterCombo;
    private com.toedter.calendar.JDateChooser dateFilterFrom;
    private javax.swing.JLabel dateFilterFromLabel;
    private javax.swing.JLabel dateFilterLabel;
    private com.toedter.calendar.JDateChooser dateFilterTo;
    private javax.swing.JLabel dateFilterToLabel;
    private javax.swing.JButton deleteButton;
    private javax.swing.JPanel detailsPanel;
    private javax.swing.JButton editButton;
    private javax.swing.JTextField employee;
    private javax.swing.JCheckBox employeeCheck;
    private javax.swing.JComboBox employeeFilterCombo;
    private javax.swing.JLabel employeeLabel;
    private javax.swing.JButton filterButton;
    private javax.swing.JPanel filterPanel;
    private javax.swing.JTextField fromDate;
    private javax.swing.JLabel fromLabel;
    private java.util.List<TimeRecording.tables.HolidayAdjustment> holidayAdjustmentList;
    private TimeRecording.enums.HolidayGrantTypeConverter holidayGrantTypeConverter;
    private javax.swing.JFormattedTextField hoursAdjusted;
    private javax.swing.JLabel hoursSpentLabel;
    private javax.swing.JButton newButton;
    private javax.swing.JButton releaseButton;
    private javax.swing.JButton revokeButton;
    private javax.swing.JTextField status;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JScrollPane tablePane;
    private javax.swing.JTextField type;
    private javax.swing.JLabel typeLabel;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables

    @Action
    public void newHolidayAdjustment() {

        HolidayAdjustment adjustment = new HolidayAdjustment();

        // Only an administrator can create an adjustment
        adjustment.setAdministratorId(myParent.getLoggedInEmployee());

        HolidayAdjustmentEditor holidayAdjustmentEditor = new HolidayAdjustmentEditor(this);
        holidayAdjustmentEditor.setAdministratorLoggedIn(administratorLoggedIn);
        holidayAdjustmentEditor.setHolidayAdjustment(adjustment);
        holidayAdjustmentEditor.setVisible(true);
        if (!holidayAdjustmentEditor.isSaveSelected()) {
            return;
        }

        try {
            // Plumb in the correct user (one used in dialog probably stale)

            Employee employee = entityManager.find(Employee.class,
                    adjustment.getEmployeeId().getEmployeeId());

            adjustment.setEmployeeId(employee);

            // Ensure the holiday adjustment is plugged into the employee's details

            employee.getHolidayAdjustments().add(adjustment);

            entityManager.getTransaction().begin();
            entityManager.persist(adjustment);

            // Reassess (and persist) holiday summary for this employee
            reassessAnnualSummary(adjustment.getEmployeeId());

            entityManager.getTransaction().commit();
            entityManager.refresh(adjustment.getEmployeeId());

            holidayAdjustmentList.add(adjustment);
            int row = holidayAdjustmentList.size() - 1;
            adjustmentTable.setRowSelectionInterval(row, row);
            adjustmentTable.scrollRectToVisible(adjustmentTable.getCellRect(row, 0, true));

        } catch (RuntimeException e) {
            LOGGER.log(Level.SEVERE, "Error creating holiday adjustment", e);
            if (entityManager.getTransaction().isActive()) {
                entityManager.getTransaction().rollback();
            }
            ErrorDialog.showError(this, e);
        }

        assessWhatShouldBeEnabled();
    }

    @Action(enabledProperty = "editable")
    public void editHolidayAdjustment() {

        HolidayAdjustmentEditor editor = new HolidayAdjustmentEditor(this);
        editor.setAdministratorLoggedIn(administratorLoggedIn);
        editor.setHolidayAdjustment(selectedAdjustment);
        editor.setVisible(true);
        if (!editor.isSaveSelected()) {
            return;
        }

        try {
            entityManager.getTransaction().begin();
            entityManager.merge(selectedAdjustment);

            // Reassess (and persist) holiday summary for this employee
            reassessAnnualSummary(selectedAdjustment.getEmployeeId());

            entityManager.getTransaction().commit();

        } catch (RuntimeException e) {
            LOGGER.log(Level.SEVERE, "Error updating holiday adjustment", e);
            if (entityManager.getTransaction().isActive()) {
                entityManager.getTransaction().rollback();
            }
            ErrorDialog.showError(this, e);
        }

        assessWhatShouldBeEnabled();
    }

    @Action
    public void deleteHolidayAdjustment() {

        int choice = JOptionPane.showConfirmDialog(this,
                "Are you sure you wish to delete the adjustment",
                "Delete Holiday Adjustment", JOptionPane.YES_NO_OPTION);

        if (choice == JOptionPane.NO_OPTION) {
            return;
        }

        HolidayAdjustment adjustment = holidayAdjustmentList.get(
                adjustmentTable.convertRowIndexToModel(
                        adjustmentTable.getSelectedRow()));

        try {
            entityManager.getTransaction().begin();

            // Delete the actual holiday
            adjustment.getEmployeeId().getHolidayAdjustments().remove(adjustment);
            entityManager.remove(adjustment);

            // Reassess (and persist) holiday summary for this employee
            reassessAnnualSummary(adjustment.getEmployeeId());

            // Complete the transaction
            entityManager.getTransaction().commit();

            // Assume that no exceptions were thrown, remove the holiday from the GUI
            holidayAdjustmentList.remove(adjustment);

            entityManager.refresh(adjustment.getEmployeeId());

        } catch (RuntimeException e) {
            LOGGER.log(Level.SEVERE, "Error deleting holiday adjustment", e);
            if (entityManager.getTransaction().isActive()) {
                entityManager.getTransaction().rollback();
            }
            ErrorDialog.showError(this, e);
        }

        assessWhatShouldBeEnabled();
    }

    private void reassessAnnualSummary(Employee employee) {

        // Reassess annual holiday spend
        new HolidayCalculations().reassessSummary(entityManager, employee);

        // Re-persist the annual holiday summary
        entityManager.merge(employee.getWorkingPatternsMaster());
    }

    @Action
    @SuppressWarnings("unchecked")
    public void applyFilter() {

        // Build a custom query with all required filters

        FilteredQuery filterQuery = new FilteredQuery(HolidayAdjustment.BASE_QUERY);
        
        if (employeeFilterable && filteredEmployee != null) {
            filterQuery.addClause(HolidayAdjustment.EMPLOYEE_FILTER);
        }

        if (adjustmentTypeFilterable && filteredAdjustmentType != null) {
            filterQuery.addClause(HolidayAdjustment.ADJUSTMENT_TYPE_FILTER);
        }
        filterQuery.addClause(HolidayAdjustment.DATE_FILTER);

        Query query = entityManager.createQuery(filterQuery.getQuery());

        if (employeeFilterable && filteredEmployee != null) {
            query.setParameter(
                    HolidayAdjustment.COL_EMPLOYEE_ID,
                    filteredEmployee);
        }

        if (adjustmentTypeFilterable && filteredAdjustmentType != null) {
            query.setParameter(
                    HolidayAdjustment.COL_ADJUSTMENT_TYPE,
                    filteredAdjustmentType);
        }

        query.setParameter(
                HolidayAdjustment.COL_LOWER_DATE,
                filteredStartDate);

        query.setParameter(
                HolidayAdjustment.COL_UPPER_DATE,
                filteredEndDate);

        holidayAdjustmentList.clear();
        holidayAdjustmentList.addAll(query.getResultList());
    }

    @Action(enabledProperty = "releaseable")
    public void releaseAdjustment() {
        changeStatus(HolidayAdjustmentStatus.RELEASED);
    }

    @Action(enabledProperty = "revokable")
    public void revokeAdjustment() {
        changeStatus(HolidayAdjustmentStatus.PREPARATION);
    }

    private void changeStatus(HolidayAdjustmentStatus status) {

        selectedAdjustment.setStatus(status);
        selectedAdjustment.setAdministratorId(myParent.getLoggedInEmployee());

        try {
            entityManager.getTransaction().begin();
            entityManager.merge(selectedAdjustment);

            // Reassess (and persist) holiday summary for this employee
            reassessAnnualSummary(selectedAdjustment.getEmployeeId());

            entityManager.getTransaction().commit();

        } catch (RuntimeException e) {
            if (entityManager.getTransaction().isActive()) {
                entityManager.getTransaction().rollback();
            }
            ErrorDialog.showError(this, e);
        }

        assessWhatShouldBeEnabled();
    }
}
